package com.freeze.demo.blockchain;

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

/**
 * <p>
 * Title: BlockChain
 * </p>
 * <p>
 * Description:
 * </p>
 * 
 * @author he_jiebing@jiuyv.com
 * @date 2021年4月9日 上午11:29:36
 */

public class BlockChain {

	public List<Block> chain = new ArrayList(); 
	// Review: 这边需要初始化
	
	private List<Transaction> currentTransactions = new ArrayList(); 
	// Review: 这边需要初始化

	public BlockChain() {
	}
	public BlockChain(List<Block> chain, List<Transaction> currentTransactions) {
		super();
		this.chain = chain;
		this.currentTransactions = currentTransactions;
	}
	
	// Review 添加方法，以输出内容
	@Override
    public String toString() {
		final StringBuilder builder = new StringBuilder();
		// Review: 此处使用函数式写法
		this.chain.stream().forEach(block -> {
			builder.append(block.toString() + ",");
		});
		
		String chain_handled = builder.toString();

        return "Blockchain(\nchains :"
		.concat(chain_handled)
		.concat("\n, ")
		.concat("current txs:") + this.currentTransactions + ")";
    }


	public List<Block> getChain() {
		return chain;
	}

	public void setChain(List<Block> chain) {
		this.chain = chain;
	}

	public List<Transaction> getCurrentTransactions() {
		return currentTransactions;
	}

	public void setCurrentTransactions(List<Transaction> currentTransactions) {
		this.currentTransactions = currentTransactions;
	}

	// Review: Java 中不需要 Blockchain self
	/**
	 * 生成新的区块
	 * 
	 * @param proof
	 * @param previousHash
	 * @return
	 */
	public Block newBlock(long proof, String previousHash) {
		Block block = new Block();
		block.setIndex(this.getChain().size() + 1);
		block.setTimestamp(System.currentTimeMillis());
		block.setTransactions(this.getCurrentTransactions());
		block.setProof(proof);
		block.setPreviousHash(previousHash);
		// 重置当前交易记录
		// Review: fix bug.
		this.setCurrentTransactions(new ArrayList());
		this.chain.add(block);
		return block;
	}

	// Review: 同上
	/**
	 * 最后一个区块
	 * 
	 * @param self
	 */
	public Block lastBlock() {
		// Question: 这一块没整明白，取得是后一个区块还是？
		// Answer: 是的，取最后一个区块
		return this.chain.get(this.chain.size() - 1);
	}


	/**
	 * hash
	 * @param block
	 * @return
	 */
	public String hash(Block block) {
		String calculatedhash = StringUtil.applySha256(block.toString());
		return calculatedhash;

	}
	/**
	 * 生成新的交易
	 * @param self
	 * @param sender
	 * @param recipient
	 * @param amount
	 */
	public void newTransaction(String sender, String recipient, Integer amount){
		Transaction transaction = new Transaction();
		transaction.setSender(sender);
		transaction.setRecipient(recipient);
		transaction.setAmount(amount);
		this.getCurrentTransactions().add(transaction);
		// TODO return self.last_block['index'] + 1
		//self.lastBlock(self)+1;
		// Review: 此处不需要，newTx 函数将新 Tx 添加到交易池中。
		
	}
	
	public long proofOfWork(BlockChain self,long lastProof){
		long proof = 0;
		while(!self.validProof(lastProof, proof)){
			proof += 1;
		}
		return proof;
		
	}
	/**
	 * TODO 
	 * @param lastProof
	 * @param proof
	 * @return
	 */
	public boolean validProof(long lastProof,long proof){
		// TODO pow 证明
		return false;
	}

}
